package com.baijia.services.impl;

import com.baijia.authentication.AccountType;
import com.baijia.common.dto.request.ChangePwdAndMobileRequest;
import com.baijia.common.dto.request.ChangePwdBySmsCodeRequest;
import com.baijia.common.dto.request.ChangePwdRequest;
import com.baijia.common.dto.request.IsRegistedUserRequest;
import com.baijia.common.dto.response.InternalResponse;
import com.baijia.common.enums.ResponseStatus;
import com.baijia.dao.OrgAccountDao;
import com.baijia.dao.OrgCascadeAccountDao;
import com.baijia.dao.PassportDao;
import com.baijia.dao.UserDao;
import com.baijia.dao.po.User;
import com.baijia.services.IAccountService;
import com.baijia.services.IUserValidationService;
import com.baijia.util.JigouPasswordUtil;
import com.baijia.util.MobileLoginUtil;

import com.google.common.collect.Maps;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Map;

import lombok.extern.slf4j.Slf4j;

@Service
@Slf4j
public class AccountServiceImpl implements IAccountService {

    private final static String COUNTRY_SYMBOL_CHINA = "CN";

    @Autowired
    private UserDao userDao;

    @Autowired
    private PassportDao passportDao;

    @Autowired
    private OrgAccountDao orgAccountDao;

    @Autowired
    private OrgCascadeAccountDao orgCascadeAccountDao;

    @Autowired
    private IUserValidationService userValidationService;

    @Override
    public InternalResponse<Map<String, Object>> isRegisted(IsRegistedUserRequest isRegistedUserRequest) {
        InternalResponse<Map<String, Object>> response = new InternalResponse<>(ResponseStatus.IS_SUCCESS);
        Map<String, Object> data = Maps.newHashMap();
        response.setData(data);

        String mobile = isRegistedUserRequest.getMobile();
        if (StringUtils.isNotEmpty(mobile)) {
            User user = userDao.getUserByMobile(mobile);
            if (user != null) {
                data.put("result", true);
                return response;
            }
        }

        data.put("result", false);
        return response;
    }

    @Override
    public InternalResponse<Map<String, Object>> updatePassword(ChangePwdRequest changePwdRequest) {

        InternalResponse<Map<String, Object>> response = null;

        boolean validationResult = userValidationService.validateUserByMobile(changePwdRequest.getMobile());
        if (!validationResult) {
            log.info("validateUserByMobile error");
            response = new InternalResponse<>(ResponseStatus.IS_FOUND_NO_USER_BY_MOBILE);
            return response;
        }

        validationResult =
            userValidationService.validatePassword(changePwdRequest.getMobile(), changePwdRequest.getPassword());
        if (!validationResult) {
            log.info("validatePassword error");
            response = new InternalResponse<>(ResponseStatus.IS_PWD_DISMATCH);
            return response;
        }

        String newPwdHash = JigouPasswordUtil.createHash(changePwdRequest.getNewPassword());
        int affectedRows = userDao.updatePwdByMobile(changePwdRequest.getMobile(), newPwdHash);
        log.debug("updatePassword affectedRows={}", affectedRows);

        if (affectedRows > 0) {
            log.info("updatePassword : success");
            response = new InternalResponse<>(ResponseStatus.IS_SUCCESS);
        } else {
            log.info("updatePassword : fail");
            response = new InternalResponse<>(ResponseStatus.IS_PWD_MOD_FAIL);
        }

        return response;
    }

    @Override
    public InternalResponse<Map<String, Object>> updatePwdAndMobileByUserId(
        ChangePwdAndMobileRequest changePwdAndMobileRequest) {
        // TODO HOLD DEV

        return null;
    }

    @Override
    public InternalResponse<Map<String, Object>> updatePwdBySmsCode(ChangePwdBySmsCodeRequest changePwdBySmsCodeRequest) {
        InternalResponse<Map<String, Object>> response = null;

        boolean validationResult = userValidationService.validateUserByMobile(changePwdBySmsCodeRequest.getMobile());
        if (!validationResult) {
            response = new InternalResponse<>(ResponseStatus.IS_FOUND_NO_USER_BY_MOBILE);
            return response;
        }

        if (!MobileLoginUtil.validPasscode(changePwdBySmsCodeRequest.getMobile(),
            changePwdBySmsCodeRequest.getSmsCode())) {
            response = new InternalResponse<>(ResponseStatus.IS_SMS_CODE_ERROR);
            return response;
        }

        String newPwdHash = JigouPasswordUtil.createHash(changePwdBySmsCodeRequest.getNewPassword());
        int affectedRows = userDao.updatePwdByMobile(changePwdBySmsCodeRequest.getMobile(), newPwdHash);
        log.debug("updatePwdBySmsCode affectedRows={}", affectedRows);

        if (affectedRows > 0) {
            log.info("updatePwdBySmsCode : success");
            response = new InternalResponse<>(ResponseStatus.IS_SUCCESS);
        } else {
            log.info("updatePwdBySmsCode : fail");
            response = new InternalResponse<>(ResponseStatus.IS_PWD_MOD_FAIL);
        }

        return response;
    }

    @Override
    public boolean updateMobileByAccountId(Integer appId, Long accountId, String countrySymbol, String countryCode,
        String mobile) {
        if (appId == null || accountId == null || StringUtils.isEmpty(countrySymbol)
            || StringUtils.isEmpty(countryCode) || StringUtils.isEmpty(mobile)) {
            log.info("updateMobileByAccountId : params invalid");
        }

        Integer affectedRow = 0;
        AccountType accountType = AccountType.getAccountTypeByCode(appId);
        switch (accountType) {
            case ORG:
            case ORG_SUB_ACCT:
                countryCode = countryCode.replace("+", ""); // 去掉+
                affectedRow = orgAccountDao.updateMobileById(countrySymbol, countryCode, mobile, accountId);
                break;
            case USER:
            case ORG_TEACHER:
                mobile = MobileLoginUtil.getI18nMobile(countrySymbol, countryCode, mobile);
                affectedRow = userDao.updateMobileById(mobile, accountId);
                break;
            case PASSPORT:
                affectedRow = passportDao.updateMobileById(mobile, accountId);
                break;
            default:
                break;
        }

        return affectedRow == 1;
    }
}